﻿using System;
using System.Diagnostics;
using System.Collections.Generic;
using System.ComponentModel;
using System.Data;
using System.Drawing;
using System.Linq;
using System.Text;
using System.Windows.Forms;
using SF = SF_Schema_Tool.SFWebService;
using MD = SF_Schema_Tool.MDWebService;
using Excel = Microsoft.Office.Interop.Excel;
using System.Reflection;


namespace SF_Schema_Tool
{
    public partial class frmMain : Form
    {
        SF.SoapClient ServerClient;
        SF.LoginResult SFLogResult;
        SF.SessionHeader sh = new SF.SessionHeader();
        SF.CallOptions co = new SF.CallOptions();
        SF.DescribeGlobalResult gResult;
        SF.PackageVersion pv = new SF.PackageVersion();
        SF.PackageVersion[] pvs;

        ///* METADATA 
        MD.MetadataPortTypeClient MetaClient;
        MD.DescribeMetadataResult mResult;
        MD.ListMetadataQuery mListQuery;
        MD.FileProperties[] lmr;
        MD.SessionHeader msh = new MD.SessionHeader();
        MD.CallOptions mco = new MD.CallOptions();
        Double version = 24.0;
        String[] reportFiles;
        //*/ 
        
        public frmMain()
        {
            
            InitializeComponent();
            chkSelectAll.Enabled = false;
            grpExport.Enabled = false;
            pvs = new SF.PackageVersion[] { pv };
            
        }

         public void loadCheckList()
        {
             if (gResult.sobjects != null)
            {
                foreach (SF.DescribeGlobalSObjectResult obj in gResult.sobjects)
                {
                    chkObjects.Items.Add(obj.name);
                }
            }

        }

        private void btnLogon_Click(object sender, EventArgs e)
        {
            txtPassword.Text = "70FC@@dm";
            txtToken.Text = "uh7eF1MngLDBtjKdgI5a6Hs1";
            txtUserName.Text = "david@truecloud.com.au.fm";
            
            if (txtPassword.TextLength == 0 || txtToken.TextLength == 0 || txtUserName.TextLength == 0)
            {
                MessageBox.Show("All login fields must be complete", "Login Error", MessageBoxButtons.OK, MessageBoxIcon.Information);
                return;
            }


            btnLogon.Enabled = false;
            
            Cursor.Current = Cursors.WaitCursor;
            lblUser.Text = "Logging in. Please wait...";
            SF.SoapClient SFClient = new SF.SoapClient();
            //Log into Salesforce
            try
            {
                SFLogResult = SFClient.login(new SF.LoginScopeHeader(), new SF.CallOptions(), txtUserName.Text, txtPassword.Text + txtToken.Text);
            }
            catch (System.ServiceModel.FaultException fe)
            {
                MessageBox.Show(fe.Message, "Login Error", MessageBoxButtons.OK, MessageBoxIcon.Error);
                btnLogon.Enabled = true;
                lblUser.Text = "";
                return;
            }
            catch (Exception err)
            {
                MessageBox.Show(err.Message, "Unknown Error", MessageBoxButtons.OK, MessageBoxIcon.Error);
                throw;
            }
             
            lblUser.Text = SFLogResult.userInfo.userFullName;

            //Once we have logged on we have to use the new URL and Session ID passed back by Salesforce
            ServerClient = new SF.SoapClient("Soap", SFLogResult.serverUrl);
            MetaClient = new MD.MetadataPortTypeClient("Metadata", SFLogResult.metadataServerUrl);
            sh.sessionId = SFLogResult.sessionId;
            msh.sessionId = SFLogResult.sessionId;
            co.client = SFLogResult.userId;
            mco.client = SFLogResult.userId;
            co.defaultNamespace = "urn:partner.soap.sforce.com";

            //Get the list of Salesforce Objects
            try
            {
                gResult = ServerClient.describeGlobal(sh, co, pvs);

            }
            catch (System.ServiceModel.FaultException fe2)
            {
                MessageBox.Show(fe2.Message, "Server Error", MessageBoxButtons.OK, MessageBoxIcon.Error);
               
                throw;
            }
            catch (Exception)
            {
                throw;
            }

            //Get the list of Metadata Objects
            /*
            try
            {
                mResult = MetaClient.describeMetadata(msh, mco, version);

                mListQuery = new MD.ListMetadataQuery();
                mListQuery.type = "Workflow"; //"WorkflowRule";//"ReportFolder";//
                
                //mListQuery.folder = "Opportunity";
                //mListQuery.
                MD.ListMetadataQuery[] mListQueries = new MD.ListMetadataQuery[] { mListQuery };
                lmr = MetaClient.listMetadata(msh, mco, mListQueries, version);
                //MD.listMetadataRequest.
                //MD.Workflow wf = (MD.Workflow)lmr[3];

                List<string> rf = new List<string>();
                foreach (MD.FileProperties fp in lmr)
                {
                    mListQuery.folder = fp.fullName;
                    // listMetadata can take more than one item at a time
                    // left as an exercise for the reader to batch up these calls.
                    MD.FileProperties[] rps = MetaClient.listMetadata(msh, mco, new MD.ListMetadataQuery[] { mListQuery }, version);
                    
                    

                    if (fp == null) continue;
                    foreach (MD.FileProperties rp in rps)
                    {
                        Console.WriteLine("{0}", rp.fileName);
                        rf.Add(rp.fullName);
                    }
                }
                reportFiles = rf.ToArray();

                // build up an unpackaged retrieve request for the list of reports.
                MD.RetrieveRequest r = new MD.RetrieveRequest();
                r.apiVersion = 24.0;
                //r.specificFiles = new string[] { "Opportunity" };
                r.unpackaged = new MD.Package();
                MD.PackageTypeMembers m = new MD.PackageTypeMembers();
                m.name = "Workflow";
                m.members = reportFiles;
                r.unpackaged.types = new MD.PackageTypeMembers[] { m };

                // start the retrieve request
                MD.AsyncResult ar = MetaClient.retrieve(msh, mco, r);
                // wait for it to complete, sleeping as necassary.
                while (!ar.done)
                {
                    System.Threading.Thread.Sleep(5 * 1000);
                    ar = MetaClient.checkStatus(msh, mco, new String[] { ar.id })[0];
                }

                // did it work ?
                if (ar.state == MD.AsyncRequestState.Error)
                    Console.WriteLine("{0} {1}", ar.statusCode, ar.message);
                else
                {
                    // now actually go get the results 
                    MD.RetrieveResult rr = MetaClient.checkRetrieveStatus(msh, mco, ar.id);
                    if (rr.messages != null)
                        foreach (MD.RetrieveMessage rm in rr.messages)
                            Console.WriteLine("{0} : {1}", rm.fileName, rm.problem);

                    // write the zipFile out to a disk file.
                    using (System.IO.FileStream fs = new System.IO.FileStream("c:\\temp\\reports.zip", System.IO.FileMode.Create))
                        fs.Write(rr.zipFile, 0, rr.zipFile.Length);
                }
                
                
                
                MessageBox.Show("Done");

            }
            catch (System.ServiceModel.FaultException fe3)
            {
                MessageBox.Show(fe3.Message, "Metadata Error", MessageBoxButtons.OK, MessageBoxIcon.Error);

                throw;
            }
            catch (Exception)
            {
                throw;
            }
            
            //Load the list into the listbox
            foreach(MD.DescribeMetadataObject mo in mResult.metadataObjects)
            {
                Debug.WriteLine(mo.directoryName);
            }
            //foreach(MD.FileProperties fp in lmr.
            */

            loadCheckList();

            chkSelectAll.Enabled = true;
            grpExport.Enabled = true;
            Cursor.Current = Cursors.Default;
            btnLogon.Enabled = true;
        }

        private void chkSelectAll_CheckedChanged(object sender, EventArgs e)
        {
            if (chkSelectAll.Checked)
            {
                for (int i = 0; i < chkObjects.Items.Count; i++)
                {
                    chkObjects.SetItemChecked(i, true);
                }
            }
            else
            {
                for (int i = 0; i < chkObjects.Items.Count; i++)
                {
                    chkObjects.SetItemChecked(i, false);
                }
            }
            
        }

        private void btnExport_Click(object sender, EventArgs e)
        {
            if (rdbExcel.Checked)
            {
                exportExcel();
            }
            

            pbarExport.Value = 0;
        }

        private void exportExcel()
        {
            Excel.Application ExcelApp = new Excel.Application();
            Excel._Workbook ExcelBook;
            Excel._Worksheet ExcelSheet;

            SF.DescribeSObjectResult sObj;
            ExcelBook = (Excel._Workbook)(ExcelApp.Workbooks.Add(Missing.Value));
            string sCustomTable;

            pbarExport.Visible = true;
            pbarExport.Minimum = 0;
            pbarExport.Maximum = chkObjects.Items.Count - 1;
            pbarExport.Value = 0;
            pbarExport.Step = 1;
            //Loop thru the checked objects

            int i,j,c;

            if (chkLandscape.Checked == true)
            {
                for (i = chkObjects.Items.Count - 1; i >= 0; i--)
                {
                    pbarExport.PerformStep();
                    if (chkObjects.GetItemChecked(i))
                    {
                        try
                        {
                            sObj = ServerClient.describeSObject(sh, co, pvs, new SF.LocaleOptions(), chkObjects.GetItemText(chkObjects.Items[i]));
                        }
                        catch (System.ServiceModel.FaultException fe2)
                        {
                            MessageBox.Show(fe2.Message, "Server Error", MessageBoxButtons.OK, MessageBoxIcon.Error);
                            throw;
                        }
                        catch (Exception)
                        {
                            throw;
                        }


                        ExcelSheet = (Excel._Worksheet)ExcelBook.Sheets.Add(Missing.Value);
                        ExcelSheet.Name = chkObjects.GetItemText(chkObjects.Items[i]);
                        if (sObj.custom)
                        {
                            sCustomTable = " (Custom)";
                        }
                        else
                        {
                            sCustomTable = "";
                        }

                        ExcelSheet.Cells[1, 1] = chkObjects.GetItemText(chkObjects.Items[i]) + sCustomTable;
                        ExcelSheet.Cells[2, 1] = "Field Label";
                        ExcelSheet.Cells[3, 1] = "Field Type";
                        ExcelSheet.Cells[4, 1] = "Picklist Values";

                        j = 2;
                        //Loop thru the sObject Fields
                        if (sObj.fields != null)
                        {
                            foreach (SF.Field fld in sObj.fields)
                            {
                                //API Field Name
                                ExcelSheet.Cells[1, j] = fld.name;
                                if (fld.autoNumber || fld.calculated)
                                {
                                    ExcelSheet.Cells[1, j] = fld.name + " (RO)";
                                    ExcelSheet.Cells[1, j].Interior.Color = System.Drawing.ColorTranslator.ToOle(System.Drawing.Color.LightCoral);
                                }

                                //Field Label
                                ExcelSheet.Cells[2, j] = fld.label.ToString();

                                //Field Type
                                ExcelSheet.Cells[3, j] = fld.type.ToString();
                                if (fld.type.ToString() == "picklist")
                                {
                                    c = 4;
                                    foreach (SF.PicklistEntry ple in fld.picklistValues)
                                    {
                                        ExcelSheet.Cells[c, j] = ple.label;
                                        c++;
                                    }
                                }
                                j++;
                            }
                        }
                    }
                }
            }
            else
            {
                for (i = chkObjects.Items.Count - 1; i >= 0; i--)
                {
                    pbarExport.PerformStep();
                    if (chkObjects.GetItemChecked(i))
                    {
                        try
                        {
                            sObj = ServerClient.describeSObject(sh, co, pvs, new SF.LocaleOptions(), chkObjects.GetItemText(chkObjects.Items[i]));
                        }
                        catch (System.ServiceModel.FaultException fe2)
                        {
                            MessageBox.Show(fe2.Message, "Server Error", MessageBoxButtons.OK, MessageBoxIcon.Error);
                            throw;
                        }
                        catch (Exception)
                        {
                            throw;
                        }


                        ExcelSheet = (Excel._Worksheet)ExcelBook.Sheets.Add(Missing.Value);
                        ExcelSheet.Name = chkObjects.GetItemText(chkObjects.Items[i]);
                        if (sObj.custom)
                        {
                            sCustomTable = " (Custom)";
                        }
                        else
                        {
                            sCustomTable = "";
                        }

                        ExcelSheet.Cells[1, 1] = chkObjects.GetItemText(chkObjects.Items[i]) + sCustomTable;
                        ExcelSheet.Cells[1, 2] = "Field Label";
                        ExcelSheet.Cells[1, 3] = "Field Type";

                        j = 2;
                        //Loop thru the sObject Fields
                        if (sObj.fields != null)
                        {
                            foreach (SF.Field fld in sObj.fields)
                            {
                                //API Field Name
                                ExcelSheet.Cells[j, 1] = fld.name;
                                if (fld.autoNumber || fld.calculated)
                                {
                                    ExcelSheet.Cells[j, 1] = fld.name + " (RO)";
                                    ExcelSheet.Cells[j, 1].Interior.Color = System.Drawing.ColorTranslator.ToOle(System.Drawing.Color.LightCoral);
                                }

                                //Field Label
                                ExcelSheet.Cells[j, 2] = fld.label.ToString();

                                //Field Type
                                ExcelSheet.Cells[j, 3] = fld.type.ToString();
                                if (fld.type.ToString() == "picklist")
                                {
                                    //c = 4;
                                    foreach (SF.PicklistEntry ple in fld.picklistValues)
                                    {
                                        j++;
                                        ExcelSheet.Cells[j, 3] = ple.label;
                                        //c++;
                                    }
                                }
                                j++;
                            }
                        }
                    }
                }
            }

            //Get sObject Details
            SaveFileDialog save = new SaveFileDialog();
            save.Filter = "xls (*.xls)|*.xls|xlsx (*.xlsx)|*.xlsx";
            
            if(save.ShowDialog() == DialogResult.OK)
            {
                ExcelBook.SaveAs(save.FileName);
                MessageBox.Show("File Saved", "Save", MessageBoxButtons.OK, MessageBoxIcon.Information);

            }
           
            ExcelBook.Close(false,Missing.Value,Missing.Value);
            ExcelBook = null;
            ExcelApp.Quit();
            ExcelApp = null;

        }

        private void fAQToolStripMenuItem_Click(object sender, EventArgs e)
        {
            //Send to TrueCloud SF Schema Web Page
        }

        private void aboutToolStripMenuItem1_Click(object sender, EventArgs e)
        {
            frmAbout about = new frmAbout();
            about.ShowDialog();
  
        }

      
   
    }
}
